package initFiles

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"strconv"
	"strings"
)

var (
	HashTermID       map[string]int64  = make(map[string]int64)  //存储单词和其对应编号
	HashTermIDOffset map[int64]int64   = make(map[int64]int64)   //存储单词ID和其对应偏移位置
	HashTermIDDocIDs map[int64][]int64 = make(map[int64][]int64) // 存储单词ID和其对应网页编号列表
	HashDocID        map[int64]string  = make(map[int64]string)  // 存储网页ID和其对应网页链接
)

// doc_id.bin：记录网页链接和编号之间的对应关系。
// term_id.bin：记录单词和编号之间的对应关系。
// index.bin：倒排索引文件，记录每个单词编号以及对应包含它的网页编号列表。
// term_offsert.bin：记录每个单词编号在倒排索引文件中的偏移位置。
//初始化，将四个文件都加载到内存中，并且组织成散列表
func InitFiles() {
	//初始化term_id.bin
	termIDFileName := "/home/fcou/go/src/SearchEngine/analysis/termId/term_id.bin"
	getTermID(termIDFileName)
	//初始化term_offsert.bin
	termIDOffsetFileName := "/home/fcou/go/src/SearchEngine/index/indexOffset/term_offset.bin"
	getTermIDOffset(termIDOffsetFileName)
	//初始化index.bin
	indexFileName := "/home/fcou/go/src/SearchEngine/index/invertedIndex/index.bin"
	getTermIDDocID(indexFileName)
	//初始化doc_id.bin
	docIDFileName := "/home/fcou/go/src/SearchEngine/collect/docId/doc_id.bin"
	getDocID(docIDFileName)
}

// 读取文件term_id.bin，并将数据存到hash表
func getTermID(termIDFileName string) {
	fmt.Println("开始读取term_id.bin文件")
	defer func() {
		fmt.Println("终止读取term_id.bin文件")
	}()
	file, err := os.Open(termIDFileName)
	if err != nil {
		fmt.Println("file open error:", err)
		return
	}
	defer file.Close()

	reader := bufio.NewReader(file)
	// 循环读取全部文件信息
	for {
		//1.先读取单词编号
		IDString, err := reader.ReadString(':')
		if err == io.EOF {
			fmt.Println("error:", err)
			break
		}
		if err != nil {
			fmt.Println(err)
			return
		}
		IDString = strings.Trim(IDString, ":") //注意去除“:”
		IDInt64, err := strconv.ParseInt(IDString, 10, 64)
		//2.再读取单词
		termString, err := reader.ReadString('\n')
		if err != nil {
			fmt.Println(err)
			return
		}
		termString = strings.Trim(termString, "\n") //注意去除“\n”
		// 3.将信息存入hash表
		HashTermID[termString] = IDInt64
	}
}

// 读取文件term_offsert.bin，并将数据存到hash表
func getTermIDOffset(termOffsetFileName string) {
	fmt.Println("开始读取term_id.bin文件")
	defer func() {
		fmt.Println("终止读取term_id.bin文件")
	}()
	file, err := os.Open(termOffsetFileName)
	if err != nil {
		fmt.Println("file open error:", err)
		return
	}
	defer file.Close()

	reader := bufio.NewReader(file)
	// 循环读取全部文件信息
	for {
		//1.先读取单词编号
		IDString, err := reader.ReadString('\t')
		if err == io.EOF {
			fmt.Println("error:", err)
			break
		}
		if err != nil {
			fmt.Println(err)
			return
		}
		IDString = strings.Trim(IDString, "\t") //注意去除“:”
		IDInt64, err := strconv.ParseInt(IDString, 10, 64)
		//2.再读取单词偏移
		offsetString, err := reader.ReadString('\r')
		if err != nil {
			fmt.Println(err)
			return
		}
		offsetString = strings.Trim(offsetString, "\r") //注意去除“\n”
		offsetInt64, err := strconv.ParseInt(offsetString, 10, 64)
		// 3.将信息存入hash表
		HashTermIDOffset[IDInt64] = offsetInt64
		reader.ReadString('\n')
	}
}

// 读取文件index.bin，并将数据存到hash表
func getTermIDDocID(indexFileName string) {
	fmt.Println("开始读取term_id.bin文件")
	defer func() {
		fmt.Println("终止读取term_id.bin文件")
	}()
	file, err := os.Open(indexFileName)
	if err != nil {
		fmt.Println("file open error:", err)
		return
	}
	defer file.Close()

	reader := bufio.NewReader(file)
	reader.ReadString('\n')
	// 循环读取全部文件信息
	for {
		//1.先读取单词编号
		IDString, err := reader.ReadString('\t')
		if err == io.EOF {
			fmt.Println("error:", err)
			break
		}
		if err != nil {
			fmt.Println(err)
			return
		}
		IDString = strings.Trim(IDString, "\t") //注意去除“:”
		IDInt64, err := strconv.ParseInt(IDString, 10, 64)
		//2.再读取网页ID
		docIDsString, err := reader.ReadString('\r')
		if err != nil {
			fmt.Println(err)
			return
		}
		docIDsString = strings.Trim(docIDsString, "\r") //注意去除“\r”
		docIDsString = strings.Trim(docIDsString, ",")  //注意去除“,”
		docIDs := strings.Split(docIDsString, ",")
		//3.将信息存入hash表
		for _, docID := range docIDs {
			docIDInt64, err := strconv.ParseInt(docID, 10, 64)
			if err != nil {
				fmt.Println(err)
				return
			}
			HashTermIDDocIDs[IDInt64] = append(HashTermIDDocIDs[IDInt64], docIDInt64)
		}
		reader.ReadString('\n')
	}
}

// 读取文件index.bin，并将数据存到hash表
func getDocID(docIDFileName string) {
	fmt.Println("开始读取doc_id.bin文件")
	defer func() {
		fmt.Println("终止读取doc_id.bin文件")
	}()
	file, err := os.Open(docIDFileName)
	if err != nil {
		fmt.Println("file open error:", err)
		return
	}
	defer file.Close()

	reader := bufio.NewReader(file)
	// 循环读取全部文件信息
	for {
		//1.先读取网页编号
		docIDString, err := reader.ReadString(':')
		if err == io.EOF {
			fmt.Println("error:", err)
			break
		}
		if err != nil {
			fmt.Println(err)
			return
		}
		docIDString = strings.Trim(docIDString, ":") //注意去除“:”
		docIDInt64, err := strconv.ParseInt(docIDString, 10, 64)
		//2.再读取网页链接
		docString, err := reader.ReadString('\r')
		if err != nil {
			fmt.Println(err)
			return
		}
		docString = strings.Trim(docString, "\r") //注意去除“\r”
		//3.将信息存入hash表
		HashDocID[docIDInt64] = docString

		reader.ReadString('\n')
	}
}
